//
//  CCI.cpp
//  p4
//
//  Created by CaoJun on 15/5/13.
//  Copyright (c) 2015年 com.baidao. All rights reserved.
//

#include "CCI.h"

#include <vector>

using namespace std;
using namespace ytx;

CCI::CCI(IndexConfig indexConfig):IndexData(indexConfig, 2)
{
    type = QuotationType::CCI;
    indexName = "CCI";
    lineData.assign(1, vector<double>());
    this->setColumn(Rect(1,1,1));
}

CCI::~CCI()
{
    
}

void CCI::updateLastest(ytx::Quotation *data){
    int n = para.value[0];
    
    n = (int) Tools::between(para.range[0].first, para.range[0].second, n);
    
    int j = data->getDataLength();
    
    if (j < n){
        return;
    }
    
    
    vector<double> MA = computeMA(data, n, &KLineItem::close, j-n)[0];

    vector<double> TP;
    vector<double> MDT;
    int i = j-n;
    double c, h, l;
    while (i < j) {
        c = data->kLineData[i].close;
        h = data->kLineData[i].high;
        l = data->kLineData[i].low;
        TP.push_back( (c+h+l)/3 );
        if (i > n - 1){
            MDT.push_back( fabs(MA[i-j+n]-c) );
        }
        else{
            MDT.push_back( 0 );
        }
        i++;
    };
    
    vector<double> MD = computeMA(MDT, n)[0];
    
    vector<double> & CCI = this->lineData[0];
    
    i = j - 1;
    
    static double constValue = 0.015;
    
    if (MD.back() == 0) {
        if (i > n - 1)
        {
            CCI.back() = CCI[i - 1];
        }
        else
        {
            CCI.back() = 1 / constValue;
        }
    }
    else {
        CCI.back() = (TP.back() - MA.back())/MD.back()/constValue;
    }
    
    
    lineData[0].back() = CCI.back();
}

void CCI::calculate(ytx::Quotation *data){
    lineData.clear();
    
    int n = para.value[0];
    
    n = (int) Tools::between(para.range[0].first, para.range[0].second, n);
    
    int i = 0, j = data->getDataLength();
    
    if (j < n){
        return;
    }
    
    double c,l,h;
    
    vector<double> MA = computeMA(data, n, &KLineItem::close)[0];
    vector<double> TP(j);
    vector<double> MDT(j);
    
    while (i < j) {
        c = data->kLineData[i].close;
        h = data->kLineData[i].high;
        l = data->kLineData[i].low;
        TP[i] = (c+h+l)/3;
        //平均绝对偏差
        if (i > n - 1){
            MDT[i]= fabs(MA[i]-c);
        }
        else{
            MDT[i] = 0;
        }
        i++;
    };
    
    vector<double> MD = computeMA(MDT, n)[0];
    
    vector<double> CCI(j);
    CCI = validation(n, CCI);
    
    i = n;
    
    static double constValue = 0.015;
    
    while (i<j) {
        if (MD[i] == 0) {
            if (i > n - 1)
            {
                CCI[i] = CCI[i - 1];
            }
            else
            {
                CCI[i] = 1 / constValue;
            }
        }
        else {
            CCI[i] = (TP[i] - MA[i])/MD[i]/constValue;
        }
        
        i++;
    }
    
    lineData.push_back(CCI);
    
}

string CCI::getCrosshairYData(int index)
{
    return Tools::Convert2FixString(lineData[0][index], toFix);
}

int CCI::getDataLength() const
{
    return hasData() ? (int)lineData[0].size() :0;
}

bool CCI::hasData() const
{
    return (lineData.size() > 0 && lineData[0].size() > 0);
}

bool CCI::hasData(int index) const
{
    
    if (hasData())
    {
        int count = (int)lineData[0].size();
        return 0 <= index && index < count;
    }
    else{
        return false;
    }
}

std::vector<std::pair<std::string, std::string> > CCI::getTopSideText(int index) const
{
    return Quotation::getTopSideText(lineData, index);
}